#ifndef CORE_H
#define CORE_H

#include "memmap.h"
#include "thread.h"
#include "fs/metafs.h"
#include "hle/__ThreadManForUser.h"

typedef enum
{
    CORE_RUNNING,
    CORE_WAITING,
    CORE_POWERDOWN
} CoreState;

typedef enum
{
    GFXTH_SETFB,
    GFXTH_FINISH,
    GFXTH_DLINT
} GfxThType;

typedef enum
{
    INTTH_READY,
    INTTH_MUSTSTART,
    INTTH_RUNNING
} IntThCbState;

#ifndef NO_THREAD
typedef enum
{
    THREAD_AUDIO,
    THREAD_GRAPHICS,
    THREAD_INTERPRETER,
    THREAD_NONE
} CoreThread;
#endif

void core_start(const char *file);
void core_stop();
void core_wait();
void core_run();
#ifdef NCURSES
void core_ncursesLoop();
#endif
void core_loop();
CoreState core_getState();
u8 core_syncHost();

#ifndef NO_THREAD
CoreThread core_getCurThread();

void core_addToGfxThStack(GfxThType type, u32 arg);
u8 core_inGfxThStack(GfxThType type);
void core_clearGfxThStack();
void core_drawSync();
TH_TYPE core_gfxTh(void *cond);

void core_callReschedule();
void core_callResumeThreads(WaitType type, u8 resched);
void core_callResumeThreadsWithId(WaitType type, u32 id, u8 resched);
void core_waitForResumeEnd();
TH_TYPE core_intTh(void *cond);

TH_TYPE core_sndTh(void *cond);
#endif

extern u8 isDbg;
extern u32 bootAddr;

#ifndef NO_THREAD
extern Condition            *intTh_ready;
extern Mutex                 intTh_mtx;
extern volatile IntThCbState intTh_state;
extern volatile u32          intTh_cbId;
extern volatile u8           intTh_cbHasArg;
extern volatile u32          intTh_cbArg;

extern Condition            *sndTh_cond;
extern Mutex                 sndTh_mtx;
#endif

#endif

